package com.dj.mingkong.portal.biz.service.music.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dj.mingkong.common.enums.StatusEnum;
import com.dj.mingkong.common.exception.ValidateException;
import com.dj.mingkong.common.infrastructure.eo.database.music.BoxEo;
import com.dj.mingkong.common.infrastructure.eo.database.music.BoxMusicEo;
import com.dj.mingkong.common.infrastructure.eo.database.music.MusicEo;
import com.dj.mingkong.common.microservice.UserContext;
import com.dj.mingkong.common.util.AssertUtils;
import com.dj.mingkong.common.util.SmartBeanCopy;
import com.dj.mingkong.portal.biz.controller.music.vo.request.BoxMusicAddVo;
import com.dj.mingkong.portal.biz.controller.music.vo.request.BoxMusicCancelVo;
import com.dj.mingkong.portal.biz.controller.music.vo.request.BoxMusicQueryVo;
import com.dj.mingkong.portal.biz.controller.music.vo.response.BoxMusicVo;
import com.dj.mingkong.portal.biz.repository.database.music.BoxMusicRepository;
import com.dj.mingkong.portal.biz.repository.database.music.BoxRepository;
import com.dj.mingkong.portal.biz.repository.database.music.MusicRepository;
import com.dj.mingkong.portal.biz.service.music.BoxMusicService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Optional;

/**
 * 音乐收藏服务实现
 *
 * @author zenglonghui
 * @date: 2022/9/1 22:46
 */
@Slf4j
@Service("boxMusicService")
public class BoxMusicServiceImpl implements BoxMusicService {
    @Resource
    private BoxMusicRepository boxMusicRepository;
    @Resource
    private MusicRepository musicRepository;
    @Resource
    private BoxRepository boxRepository;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(BoxMusicAddVo addVo) {
        final MusicEo musicEo = musicRepository.getById(addVo.getMusicId());
        AssertUtils.isNotNull(musicEo, "musicId invalid");
        final BoxEo boxEo = boxRepository.getById(addVo.getBoxId());
        checkBoxEo(boxEo);
        final Optional<BoxMusicEo> eoOptional = boxMusicRepository.oneOptByBoxIdAndMusicId(addVo.getBoxId(), addVo.getMusicId());
        eoOptional.ifPresentOrElse(boxMusicEo -> {
            if (StatusEnum.INVALID.equalsIntVal(boxMusicEo.getStatus())) {
                boxMusicEo.setStatus(StatusEnum.VALID.getIntVal());
                boxMusicRepository.updateById(boxMusicEo);
                updateBoxEo(boxEo, 1);
                updateMusicEo(musicEo, 1);
            }
        }, () -> {
            final BoxMusicEo eo = SmartBeanCopy.copy(addVo, BoxMusicEo.class);
            eo.setStatus(StatusEnum.VALID.getIntVal());
            boxMusicRepository.save(eo);
            updateBoxEo(boxEo, 1);
            updateMusicEo(musicEo, 1);
        });
    }

    private void checkBoxEo(BoxEo boxEo) {
        AssertUtils.isNotNull(boxEo, "boxId invalid");
        if (!boxEo.getUserId().equals(UserContext.getUserId())) {
            throw new ValidateException("无权限操作此歌单!");
        }
        if (StatusEnum.INVALID.equalsIntVal(boxEo.getStatus())) {
            throw new ValidateException("歌单无效!");
        }
    }

    @Override
    public Page<BoxMusicVo> pageByVo(BoxMusicQueryVo queryVo) {
        return boxMusicRepository.getMapper().listPage(Page.of(queryVo.getPage(), queryVo.getPageSize()), queryVo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancel(BoxMusicCancelVo cancelVo) {
        final MusicEo musicEo = musicRepository.getById(cancelVo.getMusicId());
        AssertUtils.isNotNull(musicEo, "musicId invalid");
        final BoxEo boxEo = boxRepository.getById(cancelVo.getBoxId());
        checkBoxEo(boxEo);
        final Optional<BoxMusicEo> eoOptional = boxMusicRepository.oneOptByBoxIdAndMusicId(cancelVo.getBoxId(), cancelVo.getMusicId());
        eoOptional.ifPresent(boxMusicEo -> {
            if (StatusEnum.VALID.equalsIntVal(boxMusicEo.getStatus())) {
                boxMusicEo.setStatus(StatusEnum.INVALID.getIntVal());
                boxMusicRepository.updateById(boxMusicEo);
                updateBoxEo(boxEo, -1);
                updateMusicEo(musicEo, -1);
            }
        });
    }

    private void updateMusicEo(MusicEo musicEo, int num) {
        musicEo.setCollectCount(musicEo.getCollectCount() + num);
        musicRepository.updateById(musicEo);
    }

    private void updateBoxEo(BoxEo boxEo, int num) {
        boxEo.setMusicUpdateTime(LocalDateTime.now())
                .setMusicCount(boxEo.getMusicCount() + num);
        boxRepository.updateById(boxEo);
    }

}
